﻿using System;
using System.Collections.Generic;                       //
using System.ComponentModel;                            //
using System.Data;                                      //Collection Array      Form1 Ln.28
using System.Drawing;                                   //Regular Expressions   Form1 Ln.606    button5_click
using System.Linq;                                      //Read Data From File   Form1 Ln.141    getPIQ(PIQ)
using System.Text;                                      //Threading             Form1 Ln.315    allToolStripMenuItem_Click && about_form Ln.61
using System.Windows.Forms;                             //Printing              Form1 Ln.550
using System.IO;                                        //
using System.Collections;                               //
using System.Globalization;                             //
using System.Threading;                                 //
using System.Drawing.Printing;
using System.Text.RegularExpressions;

namespace PaladoreQuestItem
{
    public enum element { Unknown, Fire, Water, Earth, Lightning, Demon, Shadow, Psychic, Galactic, Neutral, Physical, Ancient };
    public enum PIQ { Pali, Item, Quest };
    
    //consider adding:
        //element reference in either selection form or chart form
        //alchemy info log
        //

    //consider removing:
        //threads
        //

    public partial class Form1 : Form
    {
        //INDEX: all keys will be the name
        static internal SortedList<string, Item> itemsList = new SortedList<string, Item>();
        static internal SortedList<string, Pali> paliList = new SortedList<string, Pali>();
        static internal SortedList<string, Quest> questList = new SortedList<string, Quest>();
        static internal about_form ab; //one in memory, instantiate on open, when user closes it will null this
        PIQ listBoxPIQ;

        //DataGridView dgv = new DataGridView();
        //use later with dgv.datasource=itemslist; could make a nifty display

        public Form1()
        {
            InitializeComponent();
            ThreadPool.SetMaxThreads(1, 0); //supposed to ensure nothing will run simultaneously
            allToolStripMenuItem_Click(null, null); //calls each thread in turn to start getting the data
            //getPIQ(PIQ.Item); //it works!
            foreach (element e in Enum.GetValues(typeof(element)))
                checkedListBox1.Items.Add(e); //fill checkbox list with available elements
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            /*
            foreach (string key in itemsList.Keys)
                comboBox1.Items.Add(itemsList[key].name);
            foreach (string key in paliList.Keys)
                comboBox2.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
            foreach (string key in questList.Keys)
                comboBox3.Items.Add(questList[key].name);
             */
        }
        public void getItems() // ***deprecated!
        {
            CultureInfo ci = new CultureInfo("en-US",false); //needed for textinfo and StartsWith
            TextInfo ti = ci.TextInfo;

            string input = "";
            try
            {
                StreamReader sr = new StreamReader(@"ItemDB.csv");
                input = sr.ReadLine();
                while ((input = sr.ReadLine()) != null)
                {
                    input = ti.ToTitleCase(input); //input fields from csv will be capitalized eg. tree->Tree
                    string[] tempIn = input.Split(',');
                    //string[] paliThatDrop = new string[tempIn.Length - 4];
                    ////put remaining entries into a seperate array
                    //for (int i = 4; i < tempIn.Length; i++)
                    //{
                    //    paliThatDrop[i - 4] = tempIn[i].ToString();
                    //    if (paliThatDrop[i - 4] != "" && !paliList2.Keys.Contains(paliThatDrop[i - 4]))
                    //        paliList2.Add(paliThatDrop[i - 4], new Pali(paliThatDrop[i - 4]));
                    //}
                    if (tempIn[1].StartsWith("F", true, ci)) tempIn[1] = "Fire";
                    else if (tempIn[1].StartsWith("W", true, ci)) tempIn[1] = "Water";
                    else if (tempIn[1].StartsWith("E", true, ci)) tempIn[1] = "Earth";
                    else if (tempIn[1].StartsWith("L", true, ci)) tempIn[1] = "Lightning";
                    else if (tempIn[1].StartsWith("S", true, ci)) tempIn[1] = "Shadow";
                    else if (tempIn[1].StartsWith("D", true, ci)) tempIn[1] = "Demon";
                    else if (tempIn[1].StartsWith("G", true, ci)) tempIn[1] = "Galactic";
                    else if (tempIn[1].StartsWith("N", true, ci)) tempIn[1] = "Neutral";
                    else if (tempIn[1].StartsWith("Ph", true, ci)) tempIn[1] = "Physical";
                    else if (tempIn[1].StartsWith("Ps", true, ci)) tempIn[1] = "Psychic";
                    else if (tempIn[1].StartsWith("A", true, ci)) tempIn[1] = "Ancient";
                    else tempIn[1] = "Unknown";

                    // should eventually check to see if the item already exists but this runs first so its ok for now
                    itemsList.Add(tempIn[0], new Item(
                        tempIn[0],
                        (element)Enum.Parse(typeof(element), tempIn[1].ToString(), true),
                        Convert.ToInt32(tempIn[2].ToString()),
                        Convert.ToInt32(tempIn[3].ToString()),
                        tempIn[4],
                        tempIn[5]));
                }
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show("I couldn't find the input file :(\nPlace me in the same folder as PaliDB.csv, ItemDB.csv, and QuestDB.csv and re-run the program.");
                StreamWriter sw = new StreamWriter(@"log" + DateTime.Now.ToString("_MM_dd_HHmm") + ".txt"); //always overwrites
                sw.WriteLine("Pali: " + File.Exists(@"PaliDB.csv"));
                sw.WriteLine("Item: " + File.Exists(@"ItemDB.csv"));
                sw.WriteLine("Quest: " + File.Exists(@"QuestDB.csv"));
                sw.WriteLine(DateTime.Now.ToString());
                sw.WriteLine(e.ToString());
                sw.Close();
            }
        } // ***deprecated!
        internal static void getPIQ(PIQ piq) //todo: needs to be finished to handle all cases (quest)
        {
            CultureInfo ci = new CultureInfo("en-US", false); //needed for textinfo and StartsWith
            TextInfo ti = ci.TextInfo;

            string input = "", fileToRead = "";
            int iName = 0, iElement = 0, iRarity = 0, iLevel = 0, iMob = 0, iQuest = 0, iItem = 0, iID = 0, iEvos = 0, iXP = 0;
            try
            {
                switch (piq)
                {
                    case PIQ.Pali:
                        fileToRead = @"PaliDB.dat";//csv
                        iID = 0; iName = 1; iElement = 3; iEvos = 2; iItem = 4;
                        break;
                    case PIQ.Item:
                        fileToRead = @"ItemDB.dat";
                        iName = 0; iElement = 1; iRarity = 2; iLevel = 3; iMob = 4; iQuest = 5;
                        break;
                    case PIQ.Quest:
                        fileToRead = @"QuestDB.dat";
                        break;
                }
                StreamReader sr = new StreamReader(fileToRead);
                input = sr.ReadLine(); //reads and skips the first line (column headers)
                while ((input = sr.ReadLine()) != null) //reads again but grabs good info
                {
                    input = ti.ToTitleCase(input); //input fields from csv will be capitalized eg. tree->Tree
                    string[] tempIn = input.Split(','); //split all along commas
                    //ensures theres no mistakes. parse fails and tryparse guesses using length of string, useless
                    //cant rely on regex here to flush out partial words when startsWith is this good
                    if (tempIn[iElement].StartsWith("F", true, ci)) tempIn[iElement] = "Fire";
                    else if (tempIn[iElement].StartsWith("W", true, ci)) tempIn[iElement] = "Water";
                    else if (tempIn[iElement].StartsWith("E", true, ci)) tempIn[iElement] = "Earth";
                    else if (tempIn[iElement].StartsWith("L", true, ci)) tempIn[iElement] = "Lightning";
                    else if (tempIn[iElement].StartsWith("S", true, ci)) tempIn[iElement] = "Shadow";
                    else if (tempIn[iElement].StartsWith("D", true, ci)) tempIn[iElement] = "Demon";
                    else if (tempIn[iElement].StartsWith("G", true, ci)) tempIn[iElement] = "Galactic";
                    else if (tempIn[iElement].StartsWith("N", true, ci)) tempIn[iElement] = "Neutral";
                    else if (tempIn[iElement].StartsWith("Ph", true, ci)) tempIn[iElement] = "Physical";
                    else if (tempIn[iElement].StartsWith("Ps", true, ci)) tempIn[iElement] = "Psychic";
                    else if (tempIn[iElement].StartsWith("A", true, ci)) tempIn[iElement] = "Ancient";
                    else tempIn[iElement] = "Unknown";
                    switch (piq)
                    {
                        case PIQ.Pali:
                            string[] paliAreas = new string[tempIn.Length - 5];
                            //put remaining entries into a seperate array
                            for (int i = 5; i < tempIn.Length; i++) paliAreas[i - 5] = tempIn[i];
                            if (!paliList.Keys.Contains(tempIn[iName]))
                            {   //if it doesnt exist, add it
                                paliList.Add(tempIn[iName], new Pali(
                                    Convert.ToInt32(tempIn[iID]), tempIn[iName],
                                    (element)Enum.Parse(typeof(element), tempIn[iElement].ToString(), true),
                                    Convert.ToInt32(tempIn[iEvos]), tempIn[iItem], paliAreas));
                            }
                            else
                            {   //if it does exist, set its attributes
                                paliList[tempIn[iName]].setPaliAttributes(
                                    Convert.ToInt32(tempIn[iID]), tempIn[iName],
                                    (element)Enum.Parse(typeof(element), tempIn[iElement].ToString(), true),
                                    Convert.ToInt32(tempIn[iEvos]), tempIn[iItem], paliAreas);
                            }
                            break;
                        case PIQ.Item:
                            if (!itemsList.Keys.Contains(tempIn[iName]))
                            {   //if it doesnt exist, add it
                                itemsList.Add(tempIn[iName], new Item(
                                    tempIn[iName],
                                    (element)Enum.Parse(typeof(element), tempIn[iElement].ToString(), true),
                                    Convert.ToInt32(tempIn[iRarity].ToString()),
                                    Convert.ToInt32(tempIn[iLevel].ToString()),
                                    tempIn[iMob], tempIn[iQuest]));
                            }
                            else
                            {   //if it does exist, set its attributes
                                itemsList[tempIn[iName]].setItemAttributes(
                                    tempIn[iName],
                                    (element)Enum.Parse(typeof(element), tempIn[iElement].ToString(), true),
                                    Convert.ToInt32(tempIn[iRarity].ToString()),
                                    Convert.ToInt32(tempIn[iLevel].ToString()),
                                    tempIn[iMob], tempIn[iQuest]);
                            }
                            break;
                        case PIQ.Quest:
                            break;
                    }
                }
                Thread.Sleep(200);
                sr.Close();
            }
            catch (Exception e)
            {
                //MessageBox.Show("Sometimes the threads act funny and fire incorrectly, despite having a lock on them. This error only happens while threaded.\n\nI'm not sure what I will have to do to fix it but I'm considering just removing threads altogether because it doesnt take too long to read in the data anyways\n\nThe message usually says \"Given key not present\"\nDETAILED MESSAGE:\n" + e.Message);
                MessageBox.Show("I couldn't find the input file :(\nPlace me in the same folder as PaliDB.dat, ItemDB.dat, and QuestDB.dat and re-run the program.\n\nDETAILED MESSAGE:\n" + e.Message);
                StreamWriter sw = new StreamWriter(@"log" + DateTime.Now.ToString("_MM_dd_HHmm") + ".txt"); //always overwrites
                sw.WriteLine("Pali: " + File.Exists(@"PaliDB.csv"));
                sw.WriteLine("Item: " + File.Exists(@"ItemDB.csv"));
                sw.WriteLine("Quest: " + File.Exists(@"QuestDB.csv"));
                sw.WriteLine(DateTime.Now.ToString());
                sw.WriteLine(e.ToString());
                sw.Close();
            }
        }

        private void timer1_Tick(object sender, EventArgs e) //todo: find another use for the timer
        {
            //caused issues with multiple forms because it would check too often
            //if (checkBox1.Checked && this.TopMost != true) this.TopMost = true;
            //else if (this.TopMost != false) this.TopMost = false;
        }
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            this.Opacity = trackBar1.Value / (double)100;
        }
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            richTextBox1.Text = itemsList[comboBox1.Text].ToString();
            fillLabels(PIQ.Item, itemsList[comboBox1.Text]);
            fillElement(itemsList[comboBox1.Text].itemElement);
        }
        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            fillLabels(PIQ.Pali, paliList[comboBox2.Text.Substring(5)]);
            fillElement(paliList[comboBox2.Text.Substring(5)].paliElement);
            //substring grabs name because the index is the name not the IDnumber
            richTextBox1.Text = paliList[comboBox2.Text.Substring(5)].ToString();
        }
        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            richTextBox1.Text = questList[comboBox3.Text].ToString();
        }
        private void button1_Click(object sender, EventArgs e)
        {   //click for items
            listBoxPIQ = PIQ.Item;
            listBox1.Items.Clear();
            foreach (string key in itemsList.Keys)
                if (checkedListBox1.CheckedItems.Contains(itemsList[key].itemElement))
                    listBox1.Items.Add(string.Format("{0}", itemsList[key].name));
            //dgv.DataSource = itemsList;
            //dgv.SetBounds(200, 200, 800, 600);
            //dgv.Show();
        }
        private void button2_Click(object sender, EventArgs e)
        {   //click for pali
            listBoxPIQ = PIQ.Pali;
            listBox1.Items.Clear();
            foreach (string key in paliList.Keys)
                if (checkedListBox1.CheckedItems.Contains(paliList[key].paliElement))
                    listBox1.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
        }
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)//todo make this use fillLabels & fillElement
        {
            switch (listBoxPIQ)
            {
                case PIQ.Item:
                    Item ti = itemsList[listBox1.SelectedItem.ToString()];
                    fillLabels(PIQ.Item, ti);
                    fillElement(ti.itemElement);
                    richTextBox1.Text = ti.ToString();
                    //richTextBox1.Text = itemsList[listBox1.SelectedItem.ToString()].ToString();
                    break;
                case PIQ.Pali:
                    Pali tp = paliList[listBox1.SelectedItem.ToString().Substring(5)];
                    fillLabels(PIQ.Pali, tp);
                    fillElement(tp.paliElement);
                    richTextBox1.Text = tp.ToString();
                    //richTextBox1.Text = paliList[listBox1.SelectedItem.ToString().Substring(5)].ToString();
                    break;
                case PIQ.Quest:
                    richTextBox1.Text = questList[listBox1.SelectedItem.ToString()].ToString();
                    break;
            }
            //if (listBoxPIQ == PIQ.Item) richTextBox1.Text = itemsList2[listBox1.SelectedItem.ToString()].ToString();
            //else if (listBoxPIQ == PIQ.Pali) richTextBox1.Text = paliList2[listBox1.SelectedItem.ToString().Substring(5)].ToString();
        }
        private void paliToolStripMenuItem_Click(object sender, EventArgs e)
        {
            paliList.Clear();
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Pali); }));
            foreach (string key in paliList.Keys)
                comboBox2.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
        }
        private void itemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            itemsList.Clear();
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Item); }));
            foreach (string key in itemsList.Keys)
                comboBox1.Items.Add(itemsList[key].name);
        }
        private void questToolStripMenuItem_Click(object sender, EventArgs e)
        {
            questList.Clear();
            //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Quest); }));
        }//quest dataset not built
        private void allToolStripMenuItem_Click(object sender, EventArgs e)//changes to thread handling
        {
            paliList.Clear();
            itemsList.Clear();
            questList.Clear();
            comboBox1.Items.Clear();
            comboBox2.Items.Clear();
            comboBox3.Items.Clear();
            //getPIQ(PIQ.Item);
            getPIQ(PIQ.Pali);
            //lock (paliList)
            //{
                //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Pali); }));
                //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Item); }));
                //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Quest); }));
            //}
            //despite using a threadpool, the threads are acting unreliable outside of lock
            //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Item); }));
            //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { getPIQ(PIQ.Pali); }));
            foreach (string key in itemsList.Keys)
                comboBox1.Items.Add(itemsList[key].name);
            foreach (string key in paliList.Keys)
                comboBox2.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
            foreach (string key in questList.Keys)
                comboBox3.Items.Add(questList[key].name);
        }
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ab != null) return;
            ab = new about_form();
            ab.Show();
        }
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked) this.TopMost = true;
            if (!checkBox1.Checked) this.TopMost = false;
        }
        private void fillLabels(PIQ piq, object sender) //combobox wasnt firing this correctly before, works now
        {
            switch (piq)
            {
                case PIQ.Pali:
                    Pali tp = (Pali)sender;
                    label4.Text = "ID#" + tp.ID.ToString("000") + ":";
                    label5.Text = "Drops:";
                    label9.Text = "Element:";
                    label10.Text = "Rarity:";
                    label11.Text = "Level:";

                    if (tp.drop == null)
                    {
                        textBox1.Text = tp.name;
                        textBox2.Text = "Unknown";
                        textBox3.Text = "";
                        textBox4.Text = "";
                        textBox5.Text = "";
                    }
                    else
                    {
                        textBox1.Text = tp.name;
                        textBox2.Text = tp.drop.name;
                        textBox3.Text = tp.drop.itemElement.ToString();
                        textBox4.Text = tp.drop.rarity.ToString();
                        textBox5.Text = tp.drop.level.ToString();
                    }
                    break;
                case PIQ.Item:
                    Item ti = (Item)sender;
                    label4.Text = "Name:";
                    label5.Text = "Element:";
                    label9.Text = "Rarity:";
                    label10.Text = "Level:";
                    label11.Text = "Dropper:";

                    if (ti.mob == null)
                    {
                        textBox1.Text = ti.name;
                        textBox2.Text = ti.itemElement.ToString();
                        textBox3.Text = ti.rarity.ToString();
                        textBox4.Text = ti.level.ToString();
                        textBox5.Text = "Unknown";
                    }
                    else
                    {
                        textBox1.Text = ti.name;
                        textBox2.Text = ti.itemElement.ToString();
                        textBox3.Text = ti.rarity.ToString();
                        textBox4.Text = ti.level.ToString();
                        textBox5.Text = ti.mob.name;
                    }
                    break;
                case PIQ.Quest:
                    Quest tempQuest = (Quest)sender;
                    break;
            }
        }
        private void fillElement(element elementIn)//done 
        {
            foreach (Control c in this.Controls)
                if (c is PictureBox)
                    c.BackgroundImage = Properties.Resources.defaultImage;

            switch (elementIn)
            {
                case element.Ancient:
                    pictureBox1.BackgroundImage = Properties.Resources.ancient;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.galactic;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.psychic;
                    pictureBoxStrong3.BackgroundImage = Properties.Resources.demon;
                    break;
                case element.Demon:
                    pictureBox1.BackgroundImage = Properties.Resources.demon;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.psychic;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.neutral;
                    pictureBoxStrong3.BackgroundImage = Properties.Resources.ancient;
                    break;
                case element.Earth:
                    pictureBox1.BackgroundImage = Properties.Resources.earth;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.water;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.fire;
                    pictureBoxWeak2.BackgroundImage = Properties.Resources.psychic;
                    pictureBoxWeak3.BackgroundImage = Properties.Resources.demon;
                    break;
                case element.Fire:
                    pictureBox1.BackgroundImage = Properties.Resources.fire;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.earth;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.water;
                    break;
                case element.Galactic:
                    pictureBox1.BackgroundImage = Properties.Resources.galactic;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.physical;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.lightning;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.shadow;
                    break;
                case element.Lightning:
                    pictureBox1.BackgroundImage = Properties.Resources.lightning;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.water;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.physical;
                    break;
                case element.Neutral:
                    pictureBox1.BackgroundImage = Properties.Resources.neutral;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.shadow;
                    pictureBoxWeak2.BackgroundImage = Properties.Resources.ancient;
                    break;
                case element.Physical:
                    pictureBox1.BackgroundImage = Properties.Resources.physical;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.lightning;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.neutral;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.galactic;
                    pictureBoxWeak2.BackgroundImage = Properties.Resources.shadow;
                    pictureBoxWeak3.BackgroundImage = Properties.Resources.ancient;
                    break;
                case element.Psychic:
                    pictureBox1.BackgroundImage = Properties.Resources.psychic;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.shadow;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.demon;
                    pictureBoxStrong3.BackgroundImage = Properties.Resources.physical;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.ancient;
                    break;
                case element.Shadow:
                    pictureBox1.BackgroundImage = Properties.Resources.shadow;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.demon;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.galactic;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.psychic;
                    pictureBoxWeak2.BackgroundImage = Properties.Resources.neutral;
                    break;
                case element.Water:
                    pictureBox1.BackgroundImage = Properties.Resources.water;
                    pictureBoxStrong1.BackgroundImage = Properties.Resources.fire;
                    pictureBoxStrong2.BackgroundImage = Properties.Resources.demon;
                    pictureBoxWeak1.BackgroundImage = Properties.Resources.earth;
                    pictureBoxWeak2.BackgroundImage = Properties.Resources.lightning;
                    break;
                case element.Unknown:
                    break;
            }
        }
        private void pictureBox1_BackgroundImageChanged(object sender, EventArgs e)//todo: show element weakness+strength, maybe using a popUp or hover gimmick
        {

        }
        private void saveToFile(PIQ piq)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.ShowDialog();
            StreamWriter sw = new StreamWriter(sfd.FileName);
            switch (piq)
            {
                case PIQ.Pali:
                    sw.WriteLine("Pali case output");
                    foreach (string key in paliList.Keys)
                    {
                        string format = "";
                        if (paliList[key].drop == null)
                        {
                            format = string.Format("{0},{1},{2}",
                            paliList[key].ID, paliList[key].name, paliList[key].paliElement);
                        }
                        else
                        {
                            format = string.Format("{0},{1},{2},{3}",
                                paliList[key].ID, paliList[key].name, paliList[key].paliElement, paliList[key].drop.name);
                        }
                        sw.WriteLine(format);
                    }
                    break;
                case PIQ.Item:
                    sw.WriteLine("Item case output");
                    foreach (string key in itemsList.Keys)
                    {
                        string format = "";
                        if (itemsList[key].mob == null)
                        {
                            format = string.Format("{0},{1},{2},{3}",
                                itemsList[key].name, itemsList[key].itemElement, itemsList[key].rarity, itemsList[key].level);
                        }
                        else
                        {
                            format = string.Format("{0},{1},{2},{3},{4}",
                                itemsList[key].name, itemsList[key].itemElement, itemsList[key].rarity, itemsList[key].level, itemsList[key].mob.name);
                        }
                        sw.WriteLine(format);
                    }
                    break;
                case PIQ.Quest:
                    break;
            }

            sw.Close();
        }
        private void printCurrent()
        {
            if (textBox1.Text == "")
            {
                MessageBox.Show("You must select an ITEM or PALI from the list in order to print it");
                return;
            }
            PrintPreviewDialog ppd = new PrintPreviewDialog();
            PrintDialog pd = new PrintDialog();
            PrintDocument pdoc = new PrintDocument();

            pd.ShowDialog();
            printDocument1.PrinterSettings.PrinterName = pd.PrinterSettings.PrinterName;
            ppd.Document = this.printDocument1;
            if (ppd.ShowDialog() == DialogResult.OK)
            {
                printDocument1.Print();
            }

        }
        private void paliListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveToFile(PIQ.Pali);
        }
        private void itemListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveToFile(PIQ.Item);
        }
        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            printCurrent();
        }

        private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
        {
            Pen p = new Pen(Color.Black);
            SolidBrush b = new SolidBrush(Color.Black);
            Font f = new Font(new FontFamily("Arial"), 14, FontStyle.Bold);
            Size s = TextRenderer.MeasureText(textBox1.Text, f);
            e.Graphics.DrawString("Data for " + textBox1.Text, f, b, e.PageBounds.Width / 2 - s.Width, 50);
            e.Graphics.DrawImage(Properties.Resources.noPhoto, 40, 100, 240, 300); //placeholder for creature image
            if (pictureBox1.BackgroundImage != Properties.Resources.defaultImage) //no need for E S W if theres no element
                e.Graphics.DrawString("E  S  W", f, b, e.PageBounds.Width / 2 + 40, 270);
            e.Graphics.DrawImage(pictureBox1.BackgroundImage, e.PageBounds.Width / 2 + 40, 300, 20, 20);
            e.Graphics.DrawImage(pictureBoxStrong1.BackgroundImage, e.PageBounds.Width / 2 + 65, 300, 20, 20);
            e.Graphics.DrawImage(pictureBoxStrong2.BackgroundImage, e.PageBounds.Width / 2 + 65, 325, 20, 20);
            e.Graphics.DrawImage(pictureBoxStrong3.BackgroundImage, e.PageBounds.Width / 2 + 65, 350, 20, 20);
            e.Graphics.DrawImage(pictureBoxWeak1.BackgroundImage, e.PageBounds.Width / 2 + 90, 300, 20, 20);
            e.Graphics.DrawImage(pictureBoxWeak2.BackgroundImage, e.PageBounds.Width / 2 + 90, 325, 20, 20);
            e.Graphics.DrawImage(pictureBoxWeak3.BackgroundImage, e.PageBounds.Width / 2 + 90, 350, 20, 20);
            f = new Font(new FontFamily("Arial"), 20, FontStyle.Regular);
            //todo: use keyvaluepair as a way to get sets of info to process using a foreach
            //alternatively: find way to use fewer lines for all the printing
            e.Graphics.DrawString(label4.Text, f, b, 45, 450);
            e.Graphics.DrawString(label5.Text, f, b, 45, 480);
            e.Graphics.DrawString(label9.Text, f, b, 45, 510);
            e.Graphics.DrawString(label10.Text, f, b, 45, 540);
            e.Graphics.DrawString(label11.Text, f, b, 45, 570);
            e.Graphics.DrawString(textBox1.Text, f, b, 155, 450);
            e.Graphics.DrawString(textBox2.Text, f, b, 155, 480);
            e.Graphics.DrawString(textBox3.Text, f, b, 155, 510);
            e.Graphics.DrawString(textBox4.Text, f, b, 155, 540);
            e.Graphics.DrawString(textBox5.Text, f, b, 155, 570);
        }

        private void button3_Click(object sender, EventArgs e)
        {//search for matching items //use textbox6
            if (textBox6.Text == "") return;
            listBoxPIQ = PIQ.Item;
            listBox1.Items.Clear();
            foreach (string key in itemsList.Keys)
                if (Regex.IsMatch(key, textBox6.Text, RegexOptions.IgnoreCase))
                    listBox1.Items.Add(string.Format("{0}", itemsList[key].name));
        }

        private void button4_Click(object sender, EventArgs e)
        {//search for matching pali //use textbox6
            if (textBox6.Text == "") return;
            listBoxPIQ = PIQ.Pali;
            listBox1.Items.Clear();
            foreach (string key in paliList.Keys)
                if (Regex.IsMatch(key,textBox6.Text,RegexOptions.IgnoreCase))
                    listBox1.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
        }

        private void button5_Click(object sender, EventArgs e)
        {//search for matching elements //use textbox6
            string regexList = @"^Unknown$|^Fire$|^Water$|^Earth$|^Lightning$|^Demon$|^Shadow$|^Psychic$|^Galactic$|^Neutral$|^Physical$|^Ancient";
            CultureInfo ci = new CultureInfo("en-US", false); //needed for textinfo and StartsWith
            TextInfo ti = ci.TextInfo;
            if (Regex.IsMatch(textBox6.Text, regexList, RegexOptions.IgnoreCase))
            {
                string tempString = ti.ToTitleCase(textBox6.Text);
                listBoxPIQ = PIQ.Pali;
                listBox1.Items.Clear();
                element derp = (element)Enum.Parse(typeof(element), tempString);
                foreach (string key in paliList.Keys)
                    if (derp == paliList[key].paliElement)
                        listBox1.Items.Add(string.Format("{0:000}: {1}", paliList[key].ID, paliList[key].name));
            }
            else if (textBox6.Text != "") MessageBox.Show("\"" + textBox6.Text + "\" is invalid for element search");
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}
